package com.hospital.wx.util.validator;

import com.hospital.wx.config.SensitiveWordsConfig;
import com.hospital.wx.util.annotation.NoSensitiveWords;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * 敏感词验证器
 * 用于验证文本内容是否包含敏感词
 */
@Slf4j
@Component
public class SensitiveWordsValidator implements ConstraintValidator<NoSensitiveWords, String> {
    
    @Autowired
    private SensitiveWordsConfig config;
    
    /**
     * 记录找到的敏感词
     */
    private String foundSensitiveWord;
    
    /**
     * 记录错误类型
     */
    private String errorType;

    // 医疗相关词语白名单
    private static final Set<String> MEDICAL_WHITELIST = new HashSet<>(Arrays.asList(
            "草药",
            "中草药",
            "草",
            "黄色",
            "草本",
            "金草",
            "草本药",
            "咳嗽"
    ));

    /**
     * 验证文本内容是否合规
     * @param content 待验证的文本内容
     * @param context 验证上下文
     * @return 是否合规
     */
    @Override
    public boolean isValid(String content, ConstraintValidatorContext context) {
        if (content == null || content.trim().isEmpty()) {
            errorType = "empty";
            return false;
        }
        
        // 检查内容长度
        if (content.length() > config.getMaxLength()) {
            errorType = "length";
            return false;
        }
        
        // 检查通用敏感词
        for (String word : config.getWords().getGeneral()) {
            // 检查是否在医疗白名单中
            if (isInMedicalContext(content, word)) {
                continue;
            }
            if (content.contains(word)) {
                foundSensitiveWord = word;
                errorType = "general";
                log.warn("检测到通用敏感词: {}", word);
                return false;
            }
        }
        
        // 检查医疗相关敏感词
        for (String word : config.getWords().getMedical()) {
            if (content.contains(word)) {
                foundSensitiveWord = word;
                errorType = "medical";
                log.warn("检测到医疗敏感词: {}", word);
                return false;
            }
        }
        
        return true;
    }

    /**
     * 初始化验证器
     * @param constraintAnnotation 约束注解
     */
    @Override
    public void initialize(NoSensitiveWords constraintAnnotation) {
        // 初始化逻辑
    }
    
    /**
     * 获取错误信息
     * @return 具体的错误信息
     */
    public String getErrorMessage() {
        switch (errorType) {
            case "empty":
                return "内容不能为空";
            case "length":
                return "内容长度超过限制（最大" + config.getMaxLength() + "字符）";
            case "general":
                return "内容包含敏感词：" + foundSensitiveWord;
            case "medical":
                return "内容包含医疗敏感词：" + foundSensitiveWord;
            default:
                return "内容审核未通过";
        }
    }

    /**
     * 判断敏感词是否在医疗白名单场景中
     * @param content 完整内容
     * @param word 敏感词
     * @return 是否在白名单场景中
     */
    private boolean isInMedicalContext(String content, String word) {
        // 检查是否存在白名单组合词
        for (String whitelistWord : MEDICAL_WHITELIST) {
            if (whitelistWord.contains(word)) {
                // 如果完整内容中包含这个白名单词，则认为是合法的医疗用语
                if (content.contains(whitelistWord)) {
                    return true;
                }
            }
        }
        return false;
    }
} 